import datetime
import logging
import pytz

from concurrent.futures import ThreadPoolExecutor

from tornado.concurrent import run_on_executor

import coin.proto.options_pricing_pb2 as op_pb2
from coin.base.datetime_util import to_timestamp_int
from coin.tool.strat_monitor.util.monitor_util import (get_active_strategy,
                                                       get_topic_from_config,
                                                       get_topic_from_strat)
from coin.util.queue.config import KafkaConfig
from coin.base.query_util import query_exchange_rates
from coin.support.options_pricing.types import PricingParamsType
from coin.support.options_pricing.util.query_util import query_options_pricing_params
from coin.tool.strat_monitor.util.monitor_util import (
    load_pnl_adjust_config,
    load_pnl_adjust_config_from_transfer)
from xunkemgmt_client.client.util.query_util import (
    query_accounts,
    query_exchange_apis,
    query_strategies)


def _get_topics(strategy_config_filename, kafka_config_filename, *,
                business_unit=None, topic_type=None):
  if strategy_config_filename is not None:
    topics = get_topic_from_config(
        strategy_config_filename, kafka_config_filename,
        topic_type=topic_type)
  else:
    threshold = to_timestamp_int(
        datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) - datetime.timedelta(days=1))
    kafka_config = KafkaConfig.from_cmd_config(kafka_config_filename)
    active_strats = get_active_strategy(
        business_unit=business_unit, update_timestamp_threshold=threshold)
    topics = get_topic_from_strat(active_strats , kafka_config, topic_type=topic_type)
  return topics


class AsyncCoinInfoExecutor(object):
  def __init__(self):
    self._logger = logging.getLogger(__name__)
    self._executor = ThreadPoolExecutor(max_workers=8)

  @run_on_executor(executor='_executor')
  def query_ticker(self, base_list, quote):
    qsize = self._executor._work_queue.qsize()
    if qsize > self._executor._max_workers:
      self._logger.warning('Number of queued jobs: (%s)!', qsize)
    ticker = query_exchange_rates(base_list, quote)
    return ticker

  @run_on_executor(executor='_executor')
  def query_all_strategies(self):
    strategy_info = query_strategies(as_proto=True)
    return strategy_info

  @run_on_executor(executor='_executor')
  def query_all_accounts(self):
    return query_accounts(as_proto=True)

  @run_on_executor(executor='_executor')
  def query_all_exchange_api(self):
    return query_exchange_apis(as_proto=True)

  @run_on_executor(executor='_executor')
  def query_options_pricing_params(self) -> PricingParamsType:
    return query_options_pricing_params(models=[op_pb2.SABR])

  @run_on_executor(executor='_executor')
  def query_pnl_adjust_info(self, pnl_adj_file):
    return load_pnl_adjust_config(pnl_adj_file)

  @run_on_executor(executor='_executor')
  def query_pnl_adjust_info_from_transfer(self, request):
    return load_pnl_adjust_config_from_transfer(request)

  @run_on_executor(executor='_executor')
  def query_topics(self, strategy_config_filename, kafka_config_filename,
                   *, topic_type=None):
    return _get_topics(strategy_config_filename, kafka_config_filename,
                       topic_type=topic_type)
